package 多线程.AQS.countDownLathTest;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * CountDownLatch是一个计数器，它允许一个或多个线程等待其它线程完成操作后再继续执行，
 * 通常用来实现一个线程等待其它多个线程完成操作之后再继续执行的操作。
 *
 * CountDownLatch内部维护了一个计数器，该计数器通过CountDownLatch的构造方法指定。
 * 当调用await()方法时，它将一直阻塞，直到计数器变为0。当其它线程执行完指定的任务后，可以调用countDown()方法将计数器减一。
 * 当计数器减为0，所有的线程将同时被唤醒，然后继续执行。
 *
 * 举个例子——王者5V5模式：当10个玩家都选完英雄后会进入加载界面，直到10个人都加载到100%，才会真正进入游戏。

    CountDownLatch(int count)：CountDownLatch的构造方法，可通过count参数指定计数次数，但是要大于等于0，小于0会抛IIegalArgumentException异常。
    void await()：在计数等于0之前，会一直阻塞（在线程没被打断的情况下）。
    boolean await(long timeout,TimeUnit unit)：除非线程被中断，否则会一直阻塞，直至计数器减为0或超出指定时间timeout，当计数器为0返回true，当超过指定时间，返回false。
    void countDown()：调用一次，计数器就减1，当等于0时，释放所有线程。如果计数器的初始值就是0，那么就当没有用CountDownLatch吧。
    long getCount()：返回当前计数器的数量，可以用来测试和调试。


 */
public class TestCountDownLatch {

    public static void main(String[] args) throws InterruptedException {
        List<String> output = Collections.synchronizedList(new ArrayList<>());
        CountDownLatch countDownLatch=new CountDownLatch(5);

        List<Thread> workers = Stream.generate(() -> new Thread(new Worker(output, countDownLatch)))
                .limit(5)
                .collect(Collectors.toList());

        workers.forEach(Thread::start);
        //阻塞
        countDownLatch.await();
        output.add("计数器减为"+countDownLatch.getCount()+"，放行了！！！");
        for (String s : output) {
            System.out.println(s);
        }
    }
}